#include <stdio.h>
#include <inttypes.h>
#include <stdint.h>

#include "manchester.h"

//TODO thanks Adam Dunkels

static uint8_t manchester_encode_high[256] = {
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56,
0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x59,
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5a,
0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x65,
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x69,
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x6a,
0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x95,
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x96,
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x99,
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a,
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa9,
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, };

static uint8_t manchester_encode_low[256] = {
0x55, 0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, 0x55,
0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95,
0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa, };

static const uint8_t manchester_decode_tab[256] = {
0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x2,
0x2, 0x3, 0x3, 0x2, 0x2, 0x3, 0x3, 0x0, 0x0,
0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x2, 0x2, 0x3,
0x3, 0x2, 0x2, 0x3, 0x3, 0x4, 0x4, 0x5, 0x5,
0x4, 0x4, 0x5, 0x5, 0x6, 0x6, 0x7, 0x7, 0x6,
0x6, 0x7, 0x7, 0x4, 0x4, 0x5, 0x5, 0x4, 0x4,
0x5, 0x5, 0x6, 0x6, 0x7, 0x7, 0x6, 0x6, 0x7,
0x7, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1,
0x2, 0x2, 0x3, 0x3, 0x2, 0x2, 0x3, 0x3, 0x0,
0x0, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x2, 0x2,
0x3, 0x3, 0x2, 0x2, 0x3, 0x3, 0x4, 0x4, 0x5,
0x5, 0x4, 0x4, 0x5, 0x5, 0x6, 0x6, 0x7, 0x7,
0x6, 0x6, 0x7, 0x7, 0x4, 0x4, 0x5, 0x5, 0x4,
0x4, 0x5, 0x5, 0x6, 0x6, 0x7, 0x7, 0x6, 0x6,
0x7, 0x7, 0x8, 0x8, 0x9, 0x9, 0x8, 0x8, 0x9,
0x9, 0xa, 0xa, 0xb, 0xb, 0xa, 0xa, 0xb, 0xb,
0x8, 0x8, 0x9, 0x9, 0x8, 0x8, 0x9, 0x9, 0xa,
0xa, 0xb, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xc,
0xd, 0xd, 0xc, 0xc, 0xd, 0xd, 0xe, 0xe, 0xf,
0xf, 0xe, 0xe, 0xf, 0xf, 0xc, 0xc, 0xd, 0xd,
0xc, 0xc, 0xd, 0xd, 0xe, 0xe, 0xf, 0xf, 0xe,
0xe, 0xf, 0xf, 0x8, 0x8, 0x9, 0x9, 0x8, 0x8,
0x9, 0x9, 0xa, 0xa, 0xb, 0xb, 0xa, 0xa, 0xb,
0xb, 0x8, 0x8, 0x9, 0x9, 0x8, 0x8, 0x9, 0x9,
0xa, 0xa, 0xb, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc,
0xc, 0xd, 0xd, 0xc, 0xc, 0xd, 0xd, 0xe, 0xe,
0xf, 0xf, 0xe, 0xe, 0xf, 0xf, 0xc, 0xc, 0xd,
0xd, 0xc, 0xc, 0xd, 0xd, 0xe, 0xe, 0xf, 0xf,
0xe, 0xe, 0xf, 0xf, };

static const uint8_t manchester_valid_tab[256] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x1,
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0,
0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, };

inline uint8_t isManchester_encoded(uint8_t byte)
{
	return manchester_valid_tab[byte];
}

uint16_t manchester_encode(uint8_t* input, uint8_t* output, uint16_t size)
{
	//TODO you can optimize this by turning the table type to uint8_t
	uint16_t i, k = 0;
	for(i = 0; i<size; i++)
	{
		output[k++] = manchester_encode_high[input[i]];
		output[k++] = manchester_encode_low[input[i]];
	}
	return k;
}
uint16_t manchester_decode(uint8_t* input, uint8_t* output, uint16_t size)
{
	uint16_t i, k = 0;
	for(i = 0; i+1<size; i+=2)
	{
		output[k++] = (manchester_decode_tab[input[i]]<<4)|manchester_decode_tab[input[i+1]];
	}
	return k;
}
